<?php

/**
 * Http连接类
 */
class HttpClient {

    private $httpClient;
    private $urlInfo;

    public function __construct($url) {
        if (function_exists('curl_init')) {
            $this->httpClient = new HttpCurlClient($url);
        } else {
            $this->httpClient = new HttpSocketClient($url);
        }
        $this->urlInfo = parse_url($url);
        $this->urlInfo['path'] = isset($this->urlInfo['path']) ? $this->urlInfo['path'] : '/';
    }

    public function connect($method='GET') {
        $this->httpClient->connect($method);
    }

    public function getResponseContent() {
        return $this->httpClient->getResponseContent();
    }

    public function getResponseHeaders() {
        return $this->httpClient->getResponseHeaders();
    }

    public function getResponseHeader($header) {
        return $this->httpClient->getResponseHeader($header);
    }

    public function getResponseCode() {
        return $this->httpClient->getResponseCode();
    }

    public function getUrl() {
        return $this->httpClient->getURL();
    }

    public function getResponseContentType() {
        return $this->httpClient->getResponseContentType();
    }

    public function getUrlInfo() {
        return $this->urlInfo;
    }

    public function setUserAgent($userAgent) {
        $this->httpClient->setUserAgent($userAgent);
    }

    public function close() {
        $this->httpClient->close();
    }

    public function __destruct() {
        $this->close();
    }

}

class HttpCurlClient implements HttpInterface {

    private $url;
    private $link;
    private $responseContent;
    private $responseHeaders;
    private $responseCode;
    private $responseContentType;
    private $userAgent;

    public function __construct($url) {
        $this->url = $url;
        $this->userAgent = "CURL HTTP CLIENT";
    }

    public function connect($method='GET') {
        $this->link = curl_init($this->url);
        curl_setopt($this->link, CURLOPT_HEADER, 1);
        curl_setopt($this->link, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($this->link, CURLOPT_TIMEOUT, 5);
        curl_setopt($this->link, CURLOPT_USERAGENT, $this->userAgent);

        $this->responseContent = curl_exec($this->link);
        if (!$this->responseContent)
            throw new HttpException("conect to " . $this->url . " error");

        $this->responseCode = curl_getinfo($this->link, CURLINFO_HTTP_CODE);
        curl_close($this->link);
        $this->parseResponse();
    }

    private function parseResponse() {
        list($header, $this->responseContent) = explode("\r\n\r\n", $this->responseContent, 2);
        $header = explode("\r\n", $header);
        for ($i = 1; $i < count($header); $i++) {
            list($h1, $h2) = explode(':', $header[$i]);
            $this->responseHeaders[trim($h1)] = trim($h2);
        }
        $this->responseContentType = $this->responseHeaders['Content-Type'];
    }

    public function getResponseContent() {
        return $this->responseContent;
    }

    public function getResponseHeaders() {
        return $this->responseHeaders;
    }

    public function getResponseHeader($header) {
        return $this->responseHeaders[$header];
    }

    public function getResponseCode() {
        return $this->responseCode;
    }

    public function getURL() {
        return $this->url;
    }

    public function getResponseContentType() {
        return $this->responseContentType;
    }

    public function setUserAgent($userAgent) {

    }

    public function close() {
        if ($this->link) {
            @curl_close($this->link);
            $this->link = false;
        }
    }

    public function __destruct() {
        $this->close();
    }

}

class HttpSocketClient implements HttpInterface {

    private $url;
    private $link;
    private $responseContent;
    private $responseHeaders;
    private $responseCode;
    private $responseContentType;
    private $userAgent;

    public function __construct($url) {
        $this->url = $url;
        $this->userAgent = 'HTTP Socket Client';
    }

    public function connect($method = 'GET') {
        $url = parse_url($this->url);
        $url['port'] = isset($url['port']) ? (int) $url['port'] : 80;
        $url['path'] = isset($url['path']) ? $url['path'] : '/';

        $this->link = fsockopen($url['host'], $url['port'], $errno, $errstr, 5);

        if (!$this->link)
            throw new HttpException($errstr);


        //send request header
        $sendData = "GET {$url['path']} HTTP/1.1\r\n";
        $sendData.="UserAgent: " . $this->userAgent . "\r\n";
        $sendData.="\r\n";

        fwrite($this->link, $sendData);

        //receive data
        while (!feof($this->link)) {
            $this->responseContent.=fread($this->link, 512);
        }
        $this->close();
        $this->parseResponse();
    }

    private function parseResponse() {
        list ($headers, $this->responseContent) = explode("\r\n\r\n", $this->responseContent, 2);
        $headers = explode("\r\n", $headers);
        $t = explode(" ", $headers[0]);
        $this->responseCode = $t[1];
        unset($headers[0]);
        foreach ($headers as $h) {
            list($k, $v) = explode(":", $h);
            $this->responseHeaders[trim($k)] = trim($v);
        }
        $this->responseContentType = $this->responseHeaders['Content-Type'];
    }

    public function getResponseCode() {
        return $this->responseCode;
    }

    public function getResponseContent() {
        return $this->responseContent;
    }

    public function getResponseHeader($header) {
        return $this->responseHeaders[$header];
    }

    public function getResponseHeaders() {
        return $this->responseHeaders;
    }

    public function getURL() {
        return $this->url;
    }

    public function getResponseContentType() {
        return $this->responseContentType;
    }

    public function setUserAgent($userAgent) {
        $this->userAgent = $userAgent;
    }

    public function close() {
        if ($this->link) {
            @fclose($this->link);
            $this->link = false;
        }
    }

    public function __destruct() {
        $this->close();
    }

}

interface HttpInterface {

    public function getURL();

    public function connect($method='GET');

    public function getResponseContent();

    public function getResponseHeaders();

    public function getResponseHeader($header);

    public function getResponseCode();

    public function getResponseContentType();

    public function setUserAgent($userAgent);

    public function close();
}

class HttpException extends Exception {

    public function __construct($message) {
        parent::__construct($message);
    }

}

?>
